//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#pragma once

#include "Graphics/Systems/BatchRender.h"
#include "Graphics/Systems/Viewport.h"
#include "Graphics/Primitives/PolyLine.h"
#include "Graphics/Primitives/RectPrimitives.h"

namespace Engine
{
namespace Graphics
{

	//
	// Render 2D
	//

	class Render2D : public BaseObject
	{
	// methods
	public:
		Render2D (const EngineSubSystemsRef ess) : BaseObject(ess)
		{}

		void DrawLine (const BatchMaterial &material, const line2d &line, const color4u &color) const;
		void DrawLines (const BatchMaterial &material, const uni_array< const line2d > &lines, const color4u &color) const;

		void DrawQuad (const BatchMaterial &material, const vec2 &pos, float side, const color4u &color, bool fill) const;
		void DrawRect (const BatchMaterial &material, const vec2 &pos, const vec2 &sides, const color4u &color, bool fill, bool resolutionCorrection = false) const;
		void DrawRectRotated (const BatchMaterial &material, const vec2 &pos, const vec2 &sides, const color4u &color, float angle, bool fill, bool resolutionCorrection = false) const;

		void DrawCircle (const BatchMaterial &material, const vec2 &pos, float radius, uint segments, const color4u &color, bool fill) const;
		void DrawArc (const BatchMaterial &material, const vec2 &pos, float radius, float startAngle, float angle, uint segments, const color4u &color) const;

		//void DrawQuadTransformed (const BatchMaterial &material, const rect &region, const color4u &color, const mat2 &transform) const;

		template <typename T>
		void DrawPrimitive (const BatchMaterial &material, const T &primitive) const;

		void DrawFullscreenQuad (const BatchMaterial &material,
								 const rect region = rect(-1.0f, -1.0f, 1.0f, 1.0f),
								 const rect texcoord = rect(0.0f, 0.0f, 1.0f, 1.0f)) const;

		void DrawSpline (const BatchMaterial &material, const uni_array< const vec2 > &points,
						 const color4u &color, float step) const;

		void DrawSpline (const BatchMaterial &material, const uni_array< const vec2 > &points,
						 const color4u &color, const rect &texcoord, float width, float step, float tcStep) const;
		/*
		void DrawPolyLine (const BatchMaterial &material, const Primitives::PolyLine2D &polyLine,
							const color4u &color, float step) const;
		
		void DrawPolyLine (const BatchMaterial &material, const Primitives::PolyLine2D &polyLine,
							const color4u &color, const rect &texcoord, float width, float step, float tcStep) const;*/

	private:
		static void _DrawLineRect (const BatchRenderPtr &br, const vec2 &aspect, const BatchMaterial &material,
									const vec2 &pos, const vec2 &sides, const color4u &color);
		static void _DrawFillRect (const BatchRenderPtr &br, const vec2 &aspect, const BatchMaterial &material,
									const vec2 &pos, const vec2 &sides, const color4u &color);
		
		static void _DrawLineRectRotated (const BatchRenderPtr &br, const vec2 &aspect, const BatchMaterial &material,
											const vec2 &pos, const vec2 &sides, const color4u &color, float angle);
		static void _DrawFillRectRotated (const BatchRenderPtr &br, const vec2 &aspect, const BatchMaterial &material,
											const vec2 &pos, const vec2 &sides, const color4u &color, float angle);
		
		static void _DrawLineCircle (const BatchRenderPtr &br, const vec2 &aspect, const BatchMaterial &material,
									 const vec2 &pos, float radius, uint segments, const color4u &color);
		static void _DrawFillCircle (const BatchRenderPtr &br, const vec2 &aspect, const BatchMaterial &material,
									 const vec2 &pos, float radius, uint segments, const color4u &color);
	};




	//
	// Render 3D
	//

	class Render3D : public BaseObject
	{
	// methods
	public:
		Render3D (const EngineSubSystemsRef ess) : BaseObject(ess)
		{}
	};


	
/*
=================================================
	DrawPrimitive
=================================================
*/
	template <typename T>
	inline void Render2D::DrawPrimitive (const BatchMaterial &material, const T &primitive) const
	{
		uint16_array_t	indices;
		binary_array_t	vertices;

		indices.Resize( T::IndexCount(), false );
		vertices.Resize( T::VerticesCount() * sizeof(typename T::vertex_t), false );
		
		primitive.GetVertices( vertices.ptr() );
		primitive.GetIndices( indices.ptr(), 0 );
		
		StateManager * sm = ESS()->GetGLStateManager();

		material.Apply( sm );

		sm->BindVertexArray( T::vertex_t::GetAttribs(), (uint)vertices.ptr() );

		sm->BindIndexBuffer( 0 );
		sm->DrawElements( T::Primitive(), indices.Count(), gl_index::UINT16, (const uint8 *)indices.ptr() );
	}
	
/*
=================================================
	DrawFullscreenQuad
=================================================
*/
	inline void Render2D::DrawFullscreenQuad (const BatchMaterial &material, const rect region, const rect texcoord) const
	{
		const Primitives::Parallelogram2D	primitive( Primitives::Rect2D( region, texcoord, color4u(255) ) );
		
		StateManager * sm = ESS()->GetGLStateManager();

		material.Apply( sm );
		
		sm->BindVertexArray( Primitives::Parallelogram2D::vertex_t::GetAttribs(), (uint) &primitive );
		sm->BindIndexBuffer( 0 );

		sm->DrawArrays( gl_primitive::TRIANGLE_STRIP, 0, 4 );
	}


}	// Graphics
}	// Engine